﻿/**
 * Copyright (C) 2012 original author and authors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NGuice.Inject.Matcher;
using AopAlliance.Intercept;
using NGuice.Inject.Internal.Util;
using System.Reflection;

namespace NGuice.Inject.Internal
{
    //complete！
    /// <summary>
    /// 关联一个到方法拦截器的匹配器
    /// </summary>
    internal sealed class MethodAspect
    {
        private readonly IMatcher classMatcher;//必须为泛型IMatcher，且泛型参数必须为Type的超类
        private readonly IMatcher methodMatcher;//匹配MethodInfo超类， 必须具有MethodInfo泛型参数
        private readonly IList<IMethodInterceptor> interceptors;

        /// <summary>
        /// </summary>
        /// <param name="classMatcher">将被应用的匹配类的拦截器，例如：<code>Only(typeof(Runnable))</code></param>
        /// <param name="methodMatcher">将被应用的匹配方法的拦截器（必须具有MethodInfo泛型参数），例如：<code>AnnotatedWith(typeof(Transactional))</code></param>
        /// <param name="interceptors">被应用的拦截器</param>
        internal MethodAspect(IMatcher classMatcher, IMatcher methodMatcher, IList<IMethodInterceptor> interceptors)
        {
            this.classMatcher = Preconditions.CheckNotNull(classMatcher, "class matcher");
            Preconditions.CheckSuperGenericParameter<Type>(classMatcher);
            //if (!classMatcher.GetType().IsGenericType)
            //{
            //    throw new ArgumentException("class matcher must has generic parameters Type super type");
            //}
            //else if (!classMatcher.GetType().GetGenericTypeDefinition().IsAssignableFrom(typeof(Type)))
            //{
            //    throw new ArgumentException("class matcher must has generic parameters Type super type");
            //}
            this.methodMatcher = Preconditions.CheckNotNull(methodMatcher, "method matcher");
            Preconditions.CheckSuperGenericParameter<MethodInfo>(methodMatcher);
            //if (!methodMatcher.GetType().IsGenericType)
            //{
            //    throw new ArgumentException("method matcher must has generic parameters MethodInfo super type");
            //}
            //else if (!methodMatcher.GetType().GetGenericTypeDefinition().IsAssignableFrom(typeof(MethodInfo)))
            //{
            //    throw new ArgumentException("method matcher must has generic parameters MethodInfo super type");
            //}
            this.interceptors = Preconditions.CheckNotNull(interceptors, "interceptors");
        }

        internal MethodAspect(IMatcher classMatcher, IMatcher methodMatcher, params  IMethodInterceptor[] interceptors)
            : this(classMatcher, methodMatcher, interceptors.ToList())
        {

        }

        internal bool Matches(Type clazz)
        {
            return classMatcher.Matches(clazz);
        }

        internal bool Matches(MethodInfo method)
        {
            return methodMatcher.Matches(method);
        }

        internal IList<IMethodInterceptor> Interceptors
        {
            get
            {
                return interceptors;
            }
        }
    }
}
